package com.example.demo.api;

import com.example.demo.game.*;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.io.IOException;

@Component
public class GameAPI extends TextWebSocketHandler {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RoomManger roomManger;

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Resource
    private UserMapper userMapper;
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        GameReadyResponse response = new GameReadyResponse();
        //1 先获取到用户身份信息
        User user = (User) session.getAttributes().get("user");
        if (user == null){
            response.setOk(false);
            response.setReason("用户尚未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        //2 判定当前用户是否已经进入房间
        Room room = roomManger.getRoomByUserId(user.getUserid());
        if (room == null){
            response.setOk(false);
            response.setReason("当前用户未匹配到");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }

        //3 判断当前用户是否多开
        if (onlineUserManager.getFromGameRoom(user.getUserid()) != null ||
        onlineUserManager.getFromGameHall(user.getUserid()) != null){
            //如果一个账号一边在游戏大厅，一边在游戏房间，也视为多开
            response.setOk(true);
            response.setReason("禁止多开游戏页面");
            response.setMessage("repeatConnection");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }

        //4 设置当前玩家上线
        onlineUserManager.enterGameRoom(user.getUserid(), session);

        //5 把两个玩家加入到游戏房间中
        // 执行到当前逻辑，说明玩家已经页面跳转成功了
        synchronized (room){
            if (room.getUser1() == null){
                room.setUser1(user);
                room.setWhiteUser(user.getUserid());
                System.out.println("玩家 " + user.getUsername() + "作为玩家1，准备就绪");
                return;
            }
            if (room.getUser2() == null){
                room.setUser2(user);
                room.setWhiteUser(user.getUserid());
                System.out.println("玩家 " + user.getUsername() + "作为玩家2，准备就绪");
                noticeGameReady(room,room.getUser1(),room.getUser2());
                noticeGameReady(room,room.getUser2(),room.getUser1());
                return;
            }
        }
        // 6 如果有更多玩家尝试加入房间
        response.setOk(false);
        response.setReason("当前房间已满");
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));

    }

    private void noticeGameReady(Room room, User user1, User user2) throws IOException {
        GameReadyResponse response = new GameReadyResponse();
        response.setOk(true);
        response.setRoomId(room.getRoomId());
        response.setReason("");
        response.setMessage("gameReady");
        response.setThisUserId(user1.getUserid());
        response.setThatUserId(user2.getUserid());
        response.setWhiteUser(room.getWhiteUser());
        WebSocketSession webSocketSession = onlineUserManager.getFromGameRoom(user1.getUserid());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //1 拿到用户的身份信息
        User user = (User) session.getAttributes().get("user");
        if (user == null){
            System.out.println("[handleTextMessage]玩家尚未登录");
            return;
        }

        //2 根据玩家id获取到房间对象
        Room room = roomManger.getRoomByUserId(user.getUserid());
        room.putChess(message.getPayload());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if (user == null){
            return;
        }
        WebSocketSession webSocketSession = onlineUserManager.getFromGameRoom(user.getUserid());
        if (session ==webSocketSession){
            onlineUserManager.exitGameRoom(user.getUserid());
        }
        System.out.println("当前用户 " + user.getUsername() + "游戏房间连接异常");

        noticeThatUserWin(user);
    }

    private void noticeThatUserWin(User user) throws IOException {
        Room room = roomManger.getRoomByUserId(user.getUserid());
        if (room == null){
            //房间已经被释放了，说明已经游戏结束
            System.out.println("当前房间已经释放，无需通知对手");
            return;
        }

        // 根据房间找到对手
        User thatUser = (user == room.getUser1()) ? room.getUser2() : room.getUser1();
        //找到对手的在线状态
        WebSocketSession session = onlineUserManager.getFromGameRoom(thatUser.getUserid());
        if (session == null){
            System.out.println("双方都掉线了");
            return;
        }
        // 4 构造响应通知对手，你是获胜方
        GameResponse gameResponse = new GameResponse();
        gameResponse.setMessage("putChess");
        gameResponse.setUserId(thatUser.getUserid());
        gameResponse.setWinner(thatUser.getUserid());
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameResponse)));
        // 更新玩家分数
        int winUserId = thatUser.getUserid();
        int loseUserId = user.getUserid();
        userMapper.userWin(winUserId);
        userMapper.userLose(loseUserId);

        // 5 释放房间对象


        roomManger.remove(room.getRoomId(),room.getUser1().getUserid(),room.getUser2().getUserid());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if (user == null){
            return;
        }
        WebSocketSession webSocketSession = onlineUserManager.getFromGameRoom(user.getUserid());
        if (session ==webSocketSession){
            onlineUserManager.exitGameRoom(user.getUserid());
        }
        System.out.println("当前用户 " + user.getUsername() + " 已经离开游戏");
        //通知对手获胜
        noticeThatUserWin(user);

    }
}
